package com.buildupchao.shottingcard.runner;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

/**
 * @author buildupchao
 *         Date: 2019/3/15 19:32
 * @since JDK 1.8
 */
public class RideServerSocketAcceptor implements Runnable {

    private static final ExecutorService executors = new ThreadPoolExecutor(
            50,
            100,
            0L,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(10),
            new BasicThreadFactory.Builder().namingPattern("shotting-card-%d").build(),
            new ThreadPoolExecutor.AbortPolicy()
    );
    private static final ConcurrentHashMap<ShottingCardSocket, Long> map = new ConcurrentHashMap<ShottingCardSocket, Long>();

    private static final int MAX_ALIVE_TIME = 5000;

    public void run() {
        startExpireThreadChecker();

        ServerSocket acceptor = null;
        try {
            acceptor = new ServerSocket(8888);
            while (true) {
                Socket socket = acceptor.accept();
                executors.execute(new ShottingCardSocket(socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void setAliveTime(ShottingCardSocket thread, long aliveTime) {
        map.put(thread, aliveTime);
    }

    private void startExpireThreadChecker() {
        Thread thread = new Thread(new ExpireThreadChecker());
        thread.setName("expire-thread-checker");
        thread.start();
    }

    private class ExpireThreadChecker extends Thread {

        @Override
        public void run() {
            while (true) {
                for (ShottingCardSocket socket : map.keySet()) {
                    if (System.currentTimeMillis() - map.get(socket).longValue() > MAX_ALIVE_TIME) {
                        socket.setStop(true);
                    }
                }
            }
        }
    }
}
